package com.gmall.filter;

import com.gmall.common.utils.IpUtil;
import com.gmall.common.utils.JWTUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;

@Service
public class JWTAuthFilter implements GlobalFilter, Ordered {

    @Value("${white.ips}")
    String whiteIps;
    String[] whites = new String[]{"login","genCaptcha","test","wxpay/notifyUrl"};//

    @Autowired
    RedisTemplate redisTemplate;

    public final static String TOKEN_KEY = "token:";
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ServerHttpRequest request = exchange.getRequest();//请求
        ServerHttpResponse response = exchange.getResponse();//响应

        InetSocketAddress remoteAddress = request.getRemoteAddress();//remoteAddress 客户端地址
        //System.out.println("remoteAddress = " + remoteAddress.getAddress());
        InetSocketAddress localAddress = request.getLocalAddress();//localAddress 服务器地址
        //System.out.println("localAddress = " + localAddress.getAddress());

        //放行逻辑
        String remoteIp = IpUtil.getGatwayIpAddress(request);
        //System.out.println("remoteIp = "+ remoteIp);
        String remoteHostName = remoteAddress.getAddress().getHostName();
        //System.out.println("remoteHostName = "+ remoteHostName);
        String remoteHostAddress = remoteAddress.getAddress().getHostAddress();
        //System.out.println("remoteHostAddress = "+ remoteHostAddress);

        String[] whiteIpArray = whiteIps.split(",");//白名单  没有被允许的都是禁止的，黑名单：没有被禁止的都是允许的
        boolean isWhiteIP = false;
        for(String white:whiteIpArray){
            if(remoteHostAddress.equalsIgnoreCase(white)){
                isWhiteIP = true;
                break;
            }
        }

        if(!isWhiteIP){
            System.out.println("ip地址不是白名单");
            response.setStatusCode(HttpStatus.UNAUTHORIZED);//401
            return response.setComplete();
        }

        String path = request.getURI().getPath();
        for(String white:whites){
            if(path.contains(white)){
                return chain.filter(exchange);//白名单放行
            }
        }
        //能走到这里 一定不再白名单里

        String authorization = request.getHeaders().getFirst("Authorization");
        if(StringUtils.isEmpty(authorization)){
            System.out.println("Authorization 信息为空");
            response.setStatusCode(HttpStatus.UNAUTHORIZED);//401
            return response.setComplete();
        }
        String token = authorization.replace("Bearer ", "");
        System.out.println(authorization);
        if(StringUtils.isEmpty(token)){
            System.out.println("token 信息为空");
            response.setStatusCode(HttpStatus.UNAUTHORIZED);//401
            return response.setComplete();
        }

        try {
            String userId = JWTUtils.parseTokenAndGetUserId(token);
            String  token_from_redis = (String)redisTemplate.opsForValue().get(TOKEN_KEY + userId);
            if(token_from_redis !=null){
                //续期
                redisTemplate.expire(TOKEN_KEY + userId,5, TimeUnit.MINUTES);//重新设置
                request.mutate().header("userId",userId);//从网关处将头信息 传递给其他微服务
                return chain.filter(exchange);
            }else{//5分钟失效
                System.out.println("token 信息为空");
                response.setStatusCode(HttpStatus.UNAUTHORIZED);//401
                return response.setComplete();
            }
        }catch (RuntimeException e){
            // ExpiredJwtException, UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException
            // 过期，不支持的，格式错误的，签名错误，不合法的参数
            System.out.println("token 异常：过期，不合法 签名错误  参数错误");
            response.setStatusCode(HttpStatus.UNAUTHORIZED);//401
            return response.setComplete();
        }

    }

    @Override
    public int getOrder() {
        return -100;
    }
}
